package com.lvy.hczn.front.business.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lvy.hczn.front.business.common.CacheConstants;
import com.lvy.hczn.front.business.common.Constants;
import com.lvy.hczn.front.business.dto.Param;
import com.lvy.hczn.front.business.dto.SearchCondition;
import com.lvy.hczn.front.business.mapper.SaleOrderDetailMapper;
import com.lvy.hczn.front.business.mapper.SortTaskDetailMapper;
import com.lvy.hczn.front.business.service.GoodsBoxDetailService;
import com.lvy.hczn.front.business.service.WarehousingEntryService;
import com.lvy.hczn.front.common.core.domain.entity.SysDictData;
import com.lvy.hczn.front.common.core.redis.RedisCache;
import com.lvy.hczn.front.common.exception.UtilException;
import com.lvy.hczn.front.system.domain.business.*;
import com.lvy.hczn.front.business.mapper.SaleOrderMapper;
import com.lvy.hczn.front.business.service.SaleOrderService;
import com.lvy.hczn.front.system.mapper.SpuMapper;
import com.lvy.hczn.front.system.service.TemperatureZoneService;
import com.lvy.hczn.front.system.service.WarehouseService;
import com.lvy.hczn.front.system.service.WarehouseTemperatureZoneService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class SaleOrderServiceImpl extends ServiceImpl<SaleOrderMapper, SaleOrder> implements SaleOrderService {

    @Autowired
    private SaleOrderMapper saleOrderMapper;

    @Autowired
    private SaleOrderDetailMapper saleOrderDetailMapper;

    @Autowired
    private SpuMapper spuMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private WarehousingEntryService warehousingEntryService;

    @Autowired
    private TemperatureZoneService temperatureZoneService;

    @Autowired
    private GoodsBoxDetailService goodsBoxDetailService;

    @Autowired
    private WarehouseTemperatureZoneService warehouseTemperatureZoneService;

    @Autowired
    private WarehouseService warehouseService;

    @Autowired
    private SortTaskDetailMapper sortTaskDetailMapper;

    /**
     * 销售单状态查询
     *
     * @param saleOrder
     * @return java.util.List<com.lvy.hczn.front.system.domain.business.SaleOrder>
     * @author yw
     * @date 2023-06-12 20:35:28
     */
    @Override
    public List<SaleOrder> selectSaleOrderList(SaleOrder saleOrder) {
        if (saleOrder == null) {
            throw new UtilException("参数为空");
        }
        if (StrUtil.isEmpty(saleOrder.getType())) {
            throw new UtilException("类型为空");
        }
        if (StrUtil.isEmpty(saleOrder.getStatus())) {
            throw new UtilException("状态为空");
        }
        if (saleOrder.getDelFlag() == null) {
            saleOrder.setDelFlag(Constants.DEL_FLAG_VALID);
        }
        return saleOrderMapper.selectSaleOrderList(saleOrder);
    }

    /**
     * 退货拒收入库列表
     * 查询当前电脑所属的仓库号，在查询仓库行所包含的温区，
     * 若是多台电脑登录，最先登录的处理相同温区的退货入库
     *
     * @return
     */
    @Override
    public synchronized List<SaleOrderDetail> returnList(Param param) {
        Warehouse warehouse = warehouseService.selectLocalWarehouseFront();
        if (warehouse == null) {
            throw new UtilException("仓库信息不存在");
        }
        String dataType = com.lvy.hczn.front.common.constant.Constants.WAREHOUSING_ENTRY_DATA_TYPE_SEVEN;
        String status = com.lvy.hczn.front.common.constant.Constants.SALE_ORDER_DETAIL_STATUS_THREE;
        SaleOrderDetail saleOrderDetail = new SaleOrderDetail();
        saleOrderDetail.setDataType(dataType);
        saleOrderDetail.setStatus(status);
        saleOrderDetail.setBigProduct(param.getBigProduct());
        List<SaleOrderDetail> saleOrderDetailList = saleOrderDetailMapper.returnList(saleOrderDetail);
        List<SaleOrderDetail> saleOrderDetails = new ArrayList<>();
        /**根据查询的退货spuId，查询当前仓库是否存在，然后过滤掉当前仓库不存在的spuId返回退货详情列表到web**/
        if (saleOrderDetailList != null && !saleOrderDetailList.isEmpty()) {
            /**获取当前仓库所包含的温区**/
            WarehouseTemperatureZone warehouseTemperatureZone = new WarehouseTemperatureZone();
            List<String> distinctFields = saleOrderDetailList.stream().map(SaleOrderDetail::getTemperatureCode).distinct().collect(Collectors.toList());
            warehouseTemperatureZone.setZoneCodeList(distinctFields);
            warehouseTemperatureZone.setWarehouseId(warehouse.getId());
            warehouseTemperatureZone.setWarehouseRow(Integer.valueOf(param.getUpOrDownPolicy().getClientId()));
            List<WarehouseTemperatureZone> temperatureZoneList = warehouseTemperatureZoneService.selectList(warehouseTemperatureZone);
            Map<String, WarehouseTemperatureZone> zoneMap = temperatureZoneList.stream().collect(Collectors.toMap(WarehouseTemperatureZone::getTemperatureZoneCode, Function.identity(), (key1, key2) -> key2));

            //退货订单过滤温区，且那台电脑先登录，则记录到那台电脑上
            saleOrderDetailList.forEach(item -> {
                Object object = redisCache.get(CacheConstants.CACHE_RETURN_LIST + item.getId());
                if (object == null) {
                    if (zoneMap.containsKey(item.getTemperatureCode())) {
                        selectSortQuantity(item);
                        saleOrderDetails.add(item);
                        redisCache.set(CacheConstants.CACHE_RETURN_LIST + item.getId(), item, 3, TimeUnit.DAYS);
                    }
                } else {
                    SaleOrderDetail saleOrderDetailInfo = JSON.parseObject(JSON.toJSONString(object), SaleOrderDetail.class);
                    selectSortQuantity(saleOrderDetailInfo);
                    saleOrderDetails.add(saleOrderDetailInfo);
                }
            });
            return saleOrderDetails.stream().sorted(Comparator.comparing(SaleOrderDetail::getSpuId)).collect(Collectors.toList());
        }
        return saleOrderDetails;
    }

    /**
     * @Description 退货入库，取分拣数量，仓库缺货后，平台要求推送购买数量，退货也是退购买数量，退货入库需要显示分拣的实际数量
     * eg:平台推送商城购买的两份，仓库分拣过程中，缺货一份，实际只分拣一份，但是平台需要推送两份，退货入库会存在问题，所以，退货入库显示的是分拣的分数
     * @Param
     * @Author yw
     * @Date 2024/6/30 14:43
     * @Return
     **/
    public void selectSortQuantity(SaleOrderDetail saleOrderDetailInfo) {
        SortTaskDetail sortTaskDetail = sortTaskDetailMapper.selectOne(Wrappers.<SortTaskDetail>lambdaQuery().eq(SortTaskDetail::getSaleOrderCode, saleOrderDetailInfo.getSaleOrderCode()).eq(SortTaskDetail::getSpuId, saleOrderDetailInfo.getSpuId()).eq(SortTaskDetail::getSkuCode, saleOrderDetailInfo.getSkuCode()).eq(SortTaskDetail::getSpecCode, saleOrderDetailInfo.getSpecCode()).last("limit 1"));
        if (sortTaskDetail != null) {
            if (sortTaskDetail.getQuantity() > sortTaskDetail.getSortQuantity()) {
                saleOrderDetailInfo.setQuantity(sortTaskDetail.getQuantity() - sortTaskDetail.getSortQuantity());
            } else {
                saleOrderDetailInfo.setQuantity(sortTaskDetail.getSortQuantity());
            }

        }
    }

    /**
     * 首页显示统计数量
     *
     * @return
     */
    @Override
    public List<SaleOrderDetail> returnCount(SaleOrderDetail saleOrderDetail) {
        //首页显示数量
        String dataType = com.lvy.hczn.front.common.constant.Constants.WAREHOUSING_ENTRY_DATA_TYPE_SEVEN;
        String status = com.lvy.hczn.front.common.constant.Constants.SALE_ORDER_DETAIL_STATUS_THREE;
        saleOrderDetail.setDataType(dataType);
        saleOrderDetail.setStatus(status);
        return selectReturnCount(saleOrderDetail);
    }

    /**
     * @Description 根据状态和类型统计，根据是否大件商品分组
     * @Param
     * @Author yw
     * @Date 2024/6/28 11:15
     * @Return
     **/
    @Override
    public List<SaleOrderDetail> selectReturnCount(SaleOrderDetail saleOrderDetail) {
        if (StrUtil.isEmpty(saleOrderDetail.getDataType())) {
            throw new UtilException("数据类型为空");
        }
        if (StrUtil.isEmpty(saleOrderDetail.getStatus())) {
            throw new UtilException("状态为空");
        }
        return saleOrderDetailMapper.selectReturnCount(saleOrderDetail);
    }


    /**
     * 退货拒收入回调,退货拒收入库离开缓存位回调业务处理
     *
     * @param param
     * @return void
     * @author yw
     * @date 2023-09-14 22:40:09
     */
    @Transactional
    @Override
    public void returnCallBack(SearchCondition param) {
        if (StrUtil.hasEmpty(param.getBoxCode(), param.getClientId())) {
            throw new UtilException("货箱编号或客户端为空");
        }
        log.error("销售退货回调参数：{}", JSON.toJSONString(param));
        Object object = redisCache.get(CacheConstants.CACHE_RETURN + param.getBoxCode() + ":" + param.getClientId());
        if (object != null) {
            List<GoodsBoxDetail> goodsBoxDetailList = JSON.parseArray(String.valueOf(object), GoodsBoxDetail.class);
            if (goodsBoxDetailList != null && !goodsBoxDetailList.isEmpty()) {
                List<WarehousingEntry> list = new ArrayList<>();
                //销售单下的退单入库的商品的sku的数量且是已退货情况下的详情
                String dataType = com.lvy.hczn.front.common.constant.Constants.WAREHOUSING_ENTRY_DATA_TYPE_SEVEN;
                String status = com.lvy.hczn.front.common.constant.Constants.SALE_ORDER_DETAIL_STATUS_THREE;
                goodsBoxDetailList.forEach(goodsBoxDetail -> {
                    if (!StrUtil.isEmpty(goodsBoxDetail.getSaleOrderCode())) {
                        SaleOrderDetail saleOrderDetail = saleOrderDetailMapper.selectOne(Wrappers.<SaleOrderDetail>lambdaQuery().eq(SaleOrderDetail::getSaleOrderCode, goodsBoxDetail.getSaleOrderCode()).eq(SaleOrderDetail::getDataType, dataType).eq(SaleOrderDetail::getSpuId, goodsBoxDetail.getSpuId()).eq(SaleOrderDetail::getSkuCode, goodsBoxDetail.getSkuCode()).eq(SaleOrderDetail::getQuantity, goodsBoxDetail.getQuantity()).eq(SaleOrderDetail::getStatus, status).last("limit 1"));
                        if (saleOrderDetail != null) {
                            saleOrderDetail.setStatus(com.lvy.hczn.front.common.constant.Constants.SALE_ORDER_DETAIL_STATUS_SIX);
                            if (saleOrderDetailMapper.updateById(saleOrderDetail) == 1) {
                                convertToWarehousingEntry(goodsBoxDetail, saleOrderDetail, list);
                            }
                        }
                    }
                });

                /*没有退货入库单据详情时，置销售订单为已完成**/
                Long count = saleOrderDetailMapper.selectCount(Wrappers.<SaleOrderDetail>lambdaQuery().eq(SaleOrderDetail::getSaleOrderCode, goodsBoxDetailList.get(0).getSaleOrderCode()).eq(SaleOrderDetail::getDataType, dataType).eq(SaleOrderDetail::getStatus, status));
                if (count != null && count == 0) {
                    SaleOrder saleOrder = saleOrderMapper.selectOne(Wrappers.<SaleOrder>lambdaQuery().eq(SaleOrder::getSaleOrderCode, goodsBoxDetailList.get(0).getSaleOrderCode()).eq(SaleOrder::getStatus, status));
                    if (saleOrder != null) {
                        saleOrder.setStatus(com.lvy.hczn.front.common.constant.Constants.SALE_ORDER_DETAIL_STATUS_SIX);
                        saleOrderMapper.updateById(saleOrder);
                    }
                }
                log.error("退货入库生产入库单：{}", JSON.toJSONString(list));
                list.forEach(item -> {
                    warehousingEntryService.save(item);
                    WarehousingEntry warehousingEntry = new WarehousingEntry();
                    warehousingEntry.setEntryCode(item.getEntryCode());
                    warehousingEntry.setServiceCode(item.getServiceCode());
                    warehousingEntry.setDataType(item.getDataType());
                    warehousingEntryService.commitToPlatform(warehousingEntry, true, false);
                });
            }
        }
    }

    /**
     * 退货入库初始化仓库入库单
     *
     * @param goodsBoxDetail
     * @param saleOrderDetail
     * @param list
     * @return void
     * @author yw
     * @date 2023-09-14 23:12:30
     */
    public void convertToWarehousingEntry(GoodsBoxDetail goodsBoxDetail, SaleOrderDetail saleOrderDetail, List<WarehousingEntry> list) {
        SaleOrder saleOrder = super.getOne(Wrappers.<SaleOrder>lambdaQuery().eq(SaleOrder::getSaleOrderCode, saleOrderDetail.getSaleOrderCode()).last("limit 1"));
        WarehousingEntry warehousingEntry = new WarehousingEntry();
        warehousingEntry.setEntryCode(goodsBoxDetail.getSaleOrderCode());
        warehousingEntry.setServiceCode(saleOrder.getServiceCode());
        warehousingEntry.setSourceId(saleOrderDetail.getSourceId());
        warehousingEntry.setDataType(saleOrderDetail.getDataType());
        warehousingEntry.setWarehouseCode(saleOrder.getWarehouseCode());
        warehousingEntry.setSpuId(saleOrderDetail.getSpuId());
        warehousingEntry.setSkuCode(saleOrderDetail.getSkuCode());
        warehousingEntry.setSpecCode(saleOrderDetail.getSpecCode());
        warehousingEntry.setQuantity(saleOrderDetail.getQuantity());
        warehousingEntry.setUnit(saleOrderDetail.getUnit());
        warehousingEntry.setWeight(saleOrderDetail.getWeight());
        warehousingEntry.setSupplierCode(saleOrderDetail.getSupplierCode());
        warehousingEntry.setBatchCode(goodsBoxDetail.getBatchCode());
        warehousingEntry.setStatus("0");
        warehousingEntry.setBoxCode(goodsBoxDetail.getBoxCode());
        warehousingEntry.setProducerId(goodsBoxDetail.getProducerId());
        warehousingEntry.setWarrantyDate(goodsBoxDetail.getWarrantyDate());
        warehousingEntry.setPickTime(goodsBoxDetail.getProduceDate());
        list.add(warehousingEntry);
    }

    /**
     * 未分拣退货，更新库存到平台
     *
     * @param saleOrder
     * @return void
     * @author yw
     * @date 2023-11-09 20:46:26
     */
    @Override
    public void initCreditNoteWarehousingEntry(SaleOrder saleOrder, List<WarehousingEntry> list) {
        saleOrder.getList().forEach(saleOrderDetail -> {
            WarehousingEntry warehousingEntry = new WarehousingEntry();
            warehousingEntry.setEntryCode(saleOrder.getSaleOrderCode());
            warehousingEntry.setServiceCode(saleOrder.getServiceCode());
            warehousingEntry.setSourceId(saleOrderDetail.getSourceId());
            warehousingEntry.setDataType(com.lvy.hczn.front.common.constant.Constants.WAREHOUSING_ENTRY_DATA_TYPE_EIGHT);
            warehousingEntry.setWarehouseCode(saleOrder.getWarehouseCode());
            warehousingEntry.setSpuId(saleOrderDetail.getSpuId());
            warehousingEntry.setSkuCode(saleOrderDetail.getSkuCode());
            warehousingEntry.setSpecCode(saleOrderDetail.getSpecCode());
            warehousingEntry.setQuantity(saleOrderDetail.getQuantity());
            warehousingEntry.setUnit(saleOrderDetail.getUnit());
            warehousingEntry.setWeight(saleOrderDetail.getWeight());
            warehousingEntry.setSupplierCode(saleOrderDetail.getSupplierCode());
            warehousingEntry.setStatus("0");
            warehousingEntry.setMemberCode(saleOrder.getMemberCode());
            warehousingEntryService.initBaseData(warehousingEntry, null);

            WarehousingEntry entry = new WarehousingEntry();
            String[] ignoreProperties = {"id"};
            BeanUtil.copyProperties(warehousingEntry, entry, ignoreProperties);
            entry.setDataType(com.lvy.hczn.front.common.constant.Constants.WAREHOUSING_ENTRY_DATA_TYPE_SEVEN);
            list.add(warehousingEntry);
            list.add(entry);
        });
    }
}